package com.wgt.controller;

import com.wgt.domain.Blog;
import com.wgt.domain.Catalog;
import com.wgt.domain.User;
import com.wgt.domain.Vote;
import com.wgt.service.blog.BlogService;
import com.wgt.service.catelog.CatalogService;
import com.wgt.service.user.UserService;
import com.wgt.util.ConstraintViolationExceptionHandler;
import com.wgt.vo.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * @author wgt
 * @date 2018/1/3
 * @project new-start-blog
 */
@Slf4j
@Controller
@RequestMapping("/space")
public class UserSpaceController {

    @Autowired
    private UserService userService;

    @Autowired
    private BlogService blogService;

    @Autowired
    private CatalogService catalogService;


    /**
     * 获取用户个人设置
     * @param username
     * @param updated
     * @param model
     * @return
     */
    @GetMapping("/{username}/profile")
    @PreAuthorize("authentication.name.equals(#username)")
    public ModelAndView userProfile(@PathVariable("username")String username,@RequestParam(value = "updated",required = false)Boolean updated, Model model){
        log.info("####初始化用户设置####");
        log.info("param username >>>> [{}]",username);

        User user = userService.findByUsername(username);
        log.info("user bean content >>>> [{}]",user);
        if (updated != null && updated){
            model.addAttribute("updated",true);
            model.addAttribute("updatedMsg","信息已经保存成功");
        }
        model.addAttribute("user",user);
        return new ModelAndView("/userspace/profile", "userModel", model);
    }

    /**
     * 保存用户个人设置
     * @param username
     * @param user
     * @return
     */
    @PostMapping("/{username}/profile")
    @PreAuthorize("authentication.name.equals(#username)")
    public String saveProfile(@PathVariable("username")String username, User user){
        log.info("####用户信息更改####");

        User originalUser = userService.getUserById(user.getId());
        originalUser.setName(user.getName());
        originalUser.setEmail(user.getEmail());
        log.info("user bean content >>>> [{}]",originalUser);

        //判断是否更新密码
        String rawPassword = originalUser.getPassword();
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodePasswd = encoder.encode(user.getPassword());
        boolean isMatch = encoder.matches(rawPassword,encodePasswd);
        if (!isMatch){
            log.info(">>>>> user's password has updated ");
            originalUser.setPassword(encodePasswd);
        }

        userService.saveOrUpdateUser(originalUser);
        log.info("user info update successfully");
        return "redirect:/space/" + username + "/profile?updated=true";
    }

    /**
     * 获取用户头像信息
     * @param username
     * @param model
     * @return
     */
    @GetMapping("/{username}/header")
    @PreAuthorize("authentication.name.equals(#username)")
    public ModelAndView getHeader(@PathVariable("username")String username,Model model){
        log.info("####初始化用户头像设置####");
        log.info("param username >>>> [{}]",username);

        User user = userService.findByUsername(username);
        log.info("user bean content >>>> [{}]",user);

        model.addAttribute("user",user);
        return new ModelAndView("/userspace/avatar","userModel",model);
    }

    /**
     * 保存用户头像
     * @param username
     * @return
     */
    @PostMapping("/{username}/header")
    @PreAuthorize("authentication.name.equals(#username)")
    public ResponseEntity<Response> saveHeader(@PathVariable("username")String username, @RequestBody User user){
        log.info("####用户头像信息更新####");
        log.info("param username >>>> [{}]",username);
        log.info("param id >>>> [{}]",user.getId());
        log.info("param header url address >>>> [{}]", user.getHeader());
        User originalUser = userService.getUserById(user.getId());
        log.info("user bean content >>>> [{}]",originalUser);
        originalUser.setHeader(user.getHeader());

        userService.saveOrUpdateUser(originalUser);
        log.info("user header info update successfully");

        return ResponseEntity.ok().body(new Response(true,"保存头像信息成功",user.getHeader()));
    }

    /**
     * 获取新增博客的界面
     * @param model
     * @return
     */
    @GetMapping("/{username}/blogs/edit")
    public ModelAndView createBlog(@PathVariable("username") String username, Model model) {
        User user = userService.findByUsername(username);
        List<Catalog> catalogs = catalogService.listCatalogs(user);

        model.addAttribute("blog", new Blog(null, null, null));
        model.addAttribute("catalogs", catalogs);
        return new ModelAndView("/userspace/blogedit", "blogModel", model);
    }

    /**
     * 初始化用户主页
     * @param username
     * @param model
     * @return
     */
    @GetMapping("/{username}")
    public String userSpace(@PathVariable("username")String username, Model model){
        log.info("user request>>>>/space");
        log.info("param >>>> [{}]",username);
        User user = userService.findByUsername(username);
        model.addAttribute("user", user);
        return "redirect:/space/" + username + "/blogs";    //跳转获取博客主页
    }

    /**
     * 获取个人博客列表
     * @param username
     * @param order
     * @param category
     * @param keyword
     * @param async
     * @param pageIndex
     * @param pageSize
     * @param model
     * @return
     */
    @GetMapping("/{username}/blogs")
    public String listBlogsByOrder(@PathVariable("username") String username,
                                   @RequestParam(value="order",required=false,defaultValue="new") String order,
                                   @RequestParam(value="category",required=false ) Integer category,
                                   @RequestParam(value="keyword",required=false,defaultValue="" ) String keyword,
                                   @RequestParam(value="async",required=false) boolean async,
                                   @RequestParam(value="pageIndex",required=false,defaultValue="0") int pageIndex,
                                   @RequestParam(value="pageSize",required=false,defaultValue="10") int pageSize,
                                   Model model) {
        log.info("param username value>>>>[{}]", username);
        User  user = userService.findByUsername(username);
        log.info("get user by username user bean content [{}]",user);
        model.addAttribute("user", user);

        if (category != null) {
            log.info("find param 'category' value >>>>[{}]",category);
        }

        Page<Blog> page = null;
        if (category != null && category > 0) { // 分类查询
            Catalog catalog = catalogService.getCatalogById(category);
            Pageable pageable = new PageRequest(pageIndex, pageSize);
            page = blogService.listBlogsByCatalog(catalog, pageable);
            order = "";
        } else if (order.equals("hot")) { // 最热查询
            Sort sort = new Sort(Sort.Direction.DESC,"reading","comments","likes");
            Pageable pageable = new PageRequest(pageIndex, pageSize, sort);
            page = blogService.listBlogsByTitleLikeAndSort(user, keyword, pageable);
        } else if (order.equals("new")) { // 最新查询
            Pageable pageable = new PageRequest(pageIndex, pageSize);
            page = blogService.listBlogsByTitleLike(user, keyword, pageable);
        }

        List<Blog> list = page.getContent();	// 当前所在页面数据列表

        model.addAttribute("user", user);
        model.addAttribute("order", order);
        model.addAttribute("catalogId", category);
        model.addAttribute("keyword", keyword);
        model.addAttribute("page", page);
        model.addAttribute("blogList", list);
        return (async==true?"/userspace/u :: #mainContainerRepleace":"/userspace/u");
    }

    /**
     * 获取博客展示界面
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/{username}/blogs/{id}")
    public String getBlogById(@PathVariable("username") String username,@PathVariable("id") Integer id, Model model) {
        User principal = null;
        Blog blog = blogService.getBlogById(id);

        // 每次读取，简单的可以认为阅读量增加1次
        blogService.readingIncrease(id);

        // 判断操作用户是否是博客的所有者
        boolean isBlogOwner = false;
        if (SecurityContextHolder.getContext().getAuthentication() !=null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()
                &&  !SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString().equals("anonymousUser")) {
            principal = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if (principal !=null && username.equals(principal.getUsername())) {
                isBlogOwner = true;
            }
        }

        // 判断操作用户的点赞情况
        List<Vote> votes = blog.getVotes();
        Vote currentVote = null; // 当前用户的点赞情况

        if (principal !=null) {
            for (Vote vote : votes) {
                vote.getUser().getUsername().equals(principal.getUsername());
                currentVote = vote;
                break;
            }
        }

        model.addAttribute("isBlogOwner", isBlogOwner);
        model.addAttribute("blogModel",blog);
        model.addAttribute("currentVote",currentVote);

        return "/userspace/blog";
    }

    /**
     * 保存博客
     * @param username
     * @param blog
     * @return
     */
    @PostMapping("/{username}/blogs/edit")
    @PreAuthorize("authentication.name.equals(#username)")
    public ResponseEntity<Response> saveBlog(@PathVariable("username") String username, @RequestBody Blog blog) {
        // 对 Catalog 进行空处理
        if (blog.getCatalog().getId() == null) {
            return ResponseEntity.ok().body(new Response(false,"未选择分类"));
        }

        try {
            // 判断是修改还是新增
            if (blog.getId()!=null) {
                Blog orignalBlog = blogService.getBlogById(blog.getId());
                orignalBlog.setTitle(blog.getTitle());
                orignalBlog.setContent(blog.getContent());
                orignalBlog.setSummary(blog.getSummary());
                orignalBlog.setCatalog(blog.getCatalog());
                orignalBlog.setTags(blog.getTags());
                blogService.saveBlog(orignalBlog);
            } else {
                User user = (User)userService.findByUsername(username);
                blog.setUser(user);
                blogService.saveBlog(blog);
            }
        } catch (ConstraintViolationException e)  {
            return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
        } catch (Exception e) {
            return ResponseEntity.ok().body(new Response(false, e.getMessage()));
        }

        String redirectUrl = "/blog/space/" + username + "/blogs/" + blog.getId();
        return ResponseEntity.ok().body(new Response(true, "处理成功", redirectUrl));
    }


    /**
     * 获取编辑博客的界面
     * @param model
     * @return
     */
    @GetMapping("/{username}/blogs/edit/{id}")
    public ModelAndView editBlog(@PathVariable("username") String username,@PathVariable("id") Integer id, Model model) {
        // 获取用户分类列表
        User user = userService.findByUsername(username);
        List<Catalog> catalogs = catalogService.listCatalogs(user);

        model.addAttribute("blog", blogService.getBlogById(id));
        model.addAttribute("catalogs", catalogs);
        return new ModelAndView("/userspace/blogedit", "blogModel", model);
    }


    /**
     * 删除博客
     * @param id
     * @param username
     * @return
     */
    @DeleteMapping("/{username}/blogs/{id}")
    @PreAuthorize("authentication.name.equals(#username)")
    public ResponseEntity<Response> deleteBlog(@PathVariable("username") String username,@PathVariable("id") Integer id) {
        try {

            blogService.removeBlog(id);
        } catch (Exception e) {
            return ResponseEntity.ok().body(new Response(false, e.getMessage()));
        }

        String redirectUrl = "/blog/space/" + username + "/blogs";
        return ResponseEntity.ok().body(new Response(true, "处理成功", redirectUrl));
    }
}
